package com.ys.erp.stage_shop_service.service;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ys.erp.common.enums.RedisKey;
import com.ys.erp.common.util.DateUtil;
import com.ys.erp.common.util.MoneyUtil;
import com.ys.erp.common.util.YsThread;
import com.ys.erp.entity.data.bean.ZfbSeparateAccountOrder;
import com.ys.erp.entity.service.*;
import com.ys.erp.framework.response.PageDTO;
import com.ys.erp.stage_shop_service.bean.condition.MarkErrorFixedCondition;
import com.ys.erp.stage_shop_service.bean.condition.ZfbSeparateAccountOrderCon;
import com.ys.erp.stage_shop_service.bean.condition.ZfbSeparateAccountStatCon;
import com.ys.erp.stage_shop_service.bean.vo.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @author minamiyama
 * @date 2025/6/18
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class ShopSeparateAccountService {

    private final StringRedisTemplate stringRedisTemplate;
    private final IWfbOrderService wfbOrderService;
    private final IShopService shopService;
    private final IShopExtService shopExtService;
    private final IWfbOrderWaterService wfbOrderWaterService;
    private final IZfbSeparateAccountOrderService zfbSeparateAccountOrderService;
    private final RedisTemplate<String, String> redisTemplate;

    /**
     * 查询待转账任务队列
     */
    public List<ZfbWaitSeparateAccountVO> getPendingTasks() {
        // 获取队列中的所有任务（不删除，只查看）
        List<String> tasks = stringRedisTemplate.opsForList().range(
                RedisKey.Enums.SEPARATE_ACCOUNTS_QUEUE.getKey(), 0, -1);
        if (tasks == null || tasks.isEmpty()) {
            return new ArrayList<>();
        }
        ArrayList<ZfbWaitSeparateAccountVO> voList = new ArrayList<>();
        for (String taskJson : tasks) {
            ZfbSeparateAccountOrder.SeparateAccountDTO wfbSeparateAccountDTO = JSON.parseObject(taskJson, ZfbSeparateAccountOrder.SeparateAccountDTO.class);
            if (wfbSeparateAccountDTO != null && !ObjectUtils.isEmpty(wfbSeparateAccountDTO.getOrderNo())) {
                ZfbWaitSeparateAccountVO vo = new ZfbWaitSeparateAccountVO();
                vo.setWfbSubNo(wfbSeparateAccountDTO.getOrderNo());
                vo.setPeriod(wfbSeparateAccountDTO.getPeriod());
                vo.setAmount(MoneyUtil.long2Str(wfbSeparateAccountDTO.getAmount()));
                voList.add(vo);
            }
        }
        return voList;
    }

    /**
     * 查询转账确认中任务
     */
    public List<ZfbOrderOkIngVO> getConfirmingTasks() {
        // 获取JSON数组格式的字符串
        String confirmingJsonArrayStr = stringRedisTemplate.opsForValue().get(RedisKey.Enums.SEPARATE_ACCOUNTS_OK_ING.getKey());
        if (ObjectUtils.isEmpty(confirmingJsonArrayStr)) {
            return new ArrayList<>();
        }
        // 解析JSON数组字符串为WfbSeparateAccountDTO列表 (确认中的可能不包含失败信息，使用基类)
        List<ZfbSeparateAccountOrder> zfbOrderList = JSONArray.parseArray(confirmingJsonArrayStr, ZfbSeparateAccountOrder.class);
        if (ObjectUtils.isEmpty(zfbOrderList)) {
            return new ArrayList<>();
        }
        return zfbOrderList.stream()
                .map(order -> {
                    ZfbOrderOkIngVO vo = new ZfbOrderOkIngVO();
                    vo.setShopName(order.getShopName());
                    vo.setAmount(MoneyUtil.long2Str(order.getAmount()));
                    vo.setWfbSubNo(order.getOrderNo()+ "第" + order.getPeriod() + "期");
                    vo.setRatio(order.getSeparateRatio());
                    vo.setSeparateAmount(MoneyUtil.long2Str(order.getSeparateAmount()));
                    vo.setZfbAccount(order.getZfbAccount());
                    return vo;
                })
                .collect(Collectors.toList());
    }

    /**
     * 查询转账异常任务
     */
    public List<ZfbSeparateAccountFailVO> getErrorTasks() {
        // 获取JSON数组格式的字符串
        String failJsonArrayStr = stringRedisTemplate.opsForValue().get(RedisKey.Enums.SEPARATE_ACCOUNT_FAIL.getKey());
        if (ObjectUtils.isEmpty(failJsonArrayStr)) {
            return new ArrayList<>();
        }
        // 解析JSON数组字符串为WfbSeparateAccountFailDTO列表
        List<ZfbSeparateAccountOrder.SeparateAccountFailDTO> failDtoList = JSONArray.parseArray(failJsonArrayStr, ZfbSeparateAccountOrder.SeparateAccountFailDTO.class);
        if (failDtoList == null || failDtoList.isEmpty()) {
            return new ArrayList<>();
        }
        ArrayList<ZfbSeparateAccountFailVO> voList = new ArrayList<>();
        for (ZfbSeparateAccountOrder.SeparateAccountFailDTO failDto : failDtoList) {
            ZfbSeparateAccountFailVO vo = new ZfbSeparateAccountFailVO();
            vo.setWfbSubscriptionNo(failDto.getOrderNo());
            vo.setPeriod(failDto.getPeriod());
            vo.setShopName(failDto.getShopName());
            vo.setWfbAmount(MoneyUtil.long2Str(failDto.getAmount()));
            vo.setSeparateAmount(MoneyUtil.long2Str(failDto.getSeparateAmount()));
            vo.setZfbSeparateRatio(failDto.getRatio());
            vo.setFailDescribe(failDto.getFailDes());
            voList.add(vo);
        }
        return voList;
    }

    /**
     * 标记异常任务为已修正并重新加入队列
     */
    public void markErrorFixed(MarkErrorFixedCondition markErrorFixedCondition) {
        String wfbSubscriptionNo = markErrorFixedCondition.getWfbSubscriptionNo();
        Integer period = markErrorFixedCondition.getPeriod();
        // 1. 从Redis异常列表中移除该任务
        String failKey = RedisKey.Enums.SEPARATE_ACCOUNT_FAIL.getKey();
        String failJsonArrayStr = stringRedisTemplate.opsForValue().get(failKey);
        if (ObjectUtils.isEmpty(failJsonArrayStr) || "[]".equals(failJsonArrayStr)) {
            return;
        }
        List<ZfbSeparateAccountOrder.SeparateAccountFailDTO> failDtoList = JSONArray.parseArray(failJsonArrayStr, ZfbSeparateAccountOrder.SeparateAccountFailDTO.class);
        // 查找匹配的任务并获取金额
        ZfbSeparateAccountOrder.SeparateAccountFailDTO targetFailDto = failDtoList.stream()
                .filter(failDto -> wfbSubscriptionNo.equals(failDto.getOrderNo()) &&
                        period.equals(failDto.getPeriod()))
                .findFirst()
                .orElse(null);
        if (ObjectUtils.isEmpty(targetFailDto)) {
            return;
        }
        // 移除匹配的任务
        List<ZfbSeparateAccountOrder.SeparateAccountFailDTO> updatedFailList = failDtoList.stream()
                .filter(failDto -> !(wfbSubscriptionNo.equals(failDto.getOrderNo()) &&
                        period.equals(failDto.getPeriod())))
                .collect(Collectors.toList());
        stringRedisTemplate.opsForValue().set(failKey,  JSONArray.toJSONString(updatedFailList));
        // 创建WfbSeparateAccountDTO对象
        ZfbSeparateAccountOrder.SeparateAccountDTO wfbSeparateAccountDTO = new ZfbSeparateAccountOrder.SeparateAccountDTO();
        wfbSeparateAccountDTO.setOrderNo(targetFailDto.getOrderNo());
        wfbSeparateAccountDTO.setPeriod(targetFailDto.getPeriod());
        wfbSeparateAccountDTO.setType(targetFailDto.getType());
        wfbSeparateAccountDTO.setAmount(targetFailDto.getAmount()); // 使用从异常信息中获取的金额
        // 将DTO对象转换为JSON字符串并加入队列
        String dtoJson = JSON.toJSONString(wfbSeparateAccountDTO);
        stringRedisTemplate.opsForList().leftPush(RedisKey.Enums.SEPARATE_ACCOUNTS_QUEUE.getKey(), dtoJson);
    }

    /**
     * 分页查询支付宝分账订单
     */
    public PageDTO<ZfbSeparateAccountOrderPageVO> getZfbSeparateAccountOrderPage(ZfbSeparateAccountOrderCon queryDTO) {
        log.info("开始分页查询支付宝分账订单, 参数: {}", queryDTO);

        // 构建分页对象
        Page<ZfbSeparateAccountOrder> page = new Page<>(queryDTO.getCurrent(), queryDTO.getSize());

        // 构建查询条件
        LambdaQueryWrapper<ZfbSeparateAccountOrder> queryWrapper = buildQueryWrapper(queryDTO);

        // 执行分页查询
        Page<ZfbSeparateAccountOrder> resultPage = zfbSeparateAccountOrderService.page(page, queryWrapper);

        // 转换为VO
        List<ZfbSeparateAccountOrderPageVO> voList = resultPage.getRecords().stream()
                .map(this::convertToZfbOrderVO)
                .collect(Collectors.toList());

        log.info("分页查询支付宝分账订单完成, 总数: {}, 当前页: {}", resultPage.getTotal(), resultPage.getCurrent());
        return new PageDTO<>(resultPage.getPages(), resultPage.getTotal(), voList);
    }

    /**
     * 构建查询条件
     */
    private LambdaQueryWrapper<ZfbSeparateAccountOrder> buildQueryWrapper(ZfbSeparateAccountOrderCon queryDTO) {
        LambdaQueryWrapper<ZfbSeparateAccountOrder> queryWrapper = new LambdaQueryWrapper<>();

        // 订单号
        if (!ObjectUtils.isEmpty(queryDTO.getOrderNo())) {
            queryWrapper.like(ZfbSeparateAccountOrder::getOrderNo, queryDTO.getOrderNo().trim());
        }

        // 微分呗订单号
        if (!ObjectUtils.isEmpty(queryDTO.getWfbSubNo())) {
            queryWrapper.like(ZfbSeparateAccountOrder::getSourceOrderNo, queryDTO.getWfbSubNo().trim());
        }

        // 店铺编号
        if (!ObjectUtils.isEmpty(queryDTO.getShopCode())) {
            queryWrapper.like(ZfbSeparateAccountOrder::getShopCode, queryDTO.getShopCode().trim());
        }

        // 店铺名称
        if (!ObjectUtils.isEmpty(queryDTO.getShopName())) {
            queryWrapper.like(ZfbSeparateAccountOrder::getShopName, queryDTO.getShopName().trim());
        }

        // 支付宝账户
        if (!ObjectUtils.isEmpty(queryDTO.getZfbAccount())) {
            queryWrapper.like(ZfbSeparateAccountOrder::getZfbAccount, queryDTO.getZfbAccount().trim());
        }

        // 支付宝姓名
        if (!ObjectUtils.isEmpty(queryDTO.getZfbName())) {
            queryWrapper.like(ZfbSeparateAccountOrder::getZfbName, queryDTO.getZfbName().trim());
        }

        // 支付宝订单ID
        if (!ObjectUtils.isEmpty(queryDTO.getZfbOrderId())) {
            queryWrapper.like(ZfbSeparateAccountOrder::getZfbOrderId, queryDTO.getZfbOrderId().trim());
        }

        // 分账金额范围
        if (!ObjectUtils.isEmpty(queryDTO.getMinSeparateAmount())) {
            queryWrapper.ge(ZfbSeparateAccountOrder::getSeparateAmount, queryDTO.getMinSeparateAmount());
        }
        if (!ObjectUtils.isEmpty(queryDTO.getMaxSeparateAmount())) {
            queryWrapper.le(ZfbSeparateAccountOrder::getSeparateAmount, queryDTO.getMaxSeparateAmount());
        }

        // 交易时间范围
        if (!ObjectUtils.isEmpty(queryDTO.getTransTimeStart())) {
            queryWrapper.ge(ZfbSeparateAccountOrder::getTransTime, queryDTO.getTransTimeStart());
        }
        if (!ObjectUtils.isEmpty(queryDTO.getTransTimeEnd())) {
            queryWrapper.le(ZfbSeparateAccountOrder::getTransTime, queryDTO.getTransTimeEnd());
        }

        // 创建时间范围
        if (!ObjectUtils.isEmpty(queryDTO.getCreateTimeStart())) {
            queryWrapper.ge(ZfbSeparateAccountOrder::getCreateTime, queryDTO.getCreateTimeStart());
        }
        if (!ObjectUtils.isEmpty(queryDTO.getCreateTimeEnd())) {
            queryWrapper.le(ZfbSeparateAccountOrder::getCreateTime, queryDTO.getCreateTimeEnd());
        }

        // 排序
        String orderBy = queryDTO.getOrderBy();
        String orderDirection = queryDTO.getOrderDirection();

        if (!ObjectUtils.isEmpty(orderBy)) {
            boolean isAsc = "asc".equalsIgnoreCase(orderDirection);

            switch (orderBy.toLowerCase()) {
                case "trans_time":
                    queryWrapper.orderBy(true, isAsc, ZfbSeparateAccountOrder::getTransTime);
                    break;
                case "create_time":
                    queryWrapper.orderBy(true, isAsc, ZfbSeparateAccountOrder::getCreateTime);
                    break;
                case "init_time":
                    queryWrapper.orderBy(true, isAsc, ZfbSeparateAccountOrder::getInitTime);
                    break;
                case "wfb_separate_amount":
                    queryWrapper.orderBy(true, isAsc, ZfbSeparateAccountOrder::getSeparateAmount);
                    break;
                case "wfb_amount":
                    queryWrapper.orderBy(true, isAsc, ZfbSeparateAccountOrder::getAmount);
                    break;
                default:
                    // 默认按交易时间降序
                    queryWrapper.orderByDesc(ZfbSeparateAccountOrder::getTransTime);
                    break;
            }
        } else {
            // 默认按交易时间降序
            queryWrapper.orderByDesc(ZfbSeparateAccountOrder::getTransTime);
        }

        return queryWrapper;
    }

    /**
     * 转换实体为VO
     */
    private ZfbSeparateAccountOrderPageVO convertToZfbOrderVO(ZfbSeparateAccountOrder entity) {
        ZfbSeparateAccountOrderPageVO vo = new ZfbSeparateAccountOrderPageVO();

        vo.setId(entity.getId())
          .setOrderNo(entity.getOrderNo())
          .setWfbSubNo(entity.getSourceOrderNo())
          .setWfbPeriod(entity.getPeriod())
          .setShopCode(entity.getShopCode())
          .setShopName(entity.getShopName())
          .setSeparateRatio(entity.getSeparateRatio())
          .setOriginZfbAccount(entity.getOriginZfbAccount())
          .setZfbAccount(entity.getZfbAccount())
          .setZfbIdCard(entity.getZfbIdCard())
          .setZfbName(entity.getZfbName())
          .setZfbOrderId(entity.getZfbOrderId())
          .setZfbPayFundOrderId(entity.getZfbPayFundOrderId())
          .setZfbBizScene(entity.getZfbBizScene())
          .setZfbProductCode(entity.getZfbProductCode())
          .setInitTime(entity.getInitTime())
          .setTransTime(entity.getTransTime())
          .setCreateTime(entity.getCreateTime())
          .setUpdateTime(entity.getUpdateTime());

        // 金额转换：分转元
        if (entity.getAmount() != null) {
            vo.setWfbAmount(new BigDecimal(entity.getAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
        }
        if (entity.getSeparateAmount() != null) {
            vo.setWfbSeparateAmount(new BigDecimal(entity.getSeparateAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
        }

        return vo;
    }

    /**
     * 查询分账名单
     */
    public List<SeparateAccountListVO> getSeparateAccountList() {
        List<SeparateAccountListVO> resultList = new ArrayList<>();
        // 查询以 "wfb:need_separate_accounts:hz123cwmy@163.com" 开头的所有Redis键
        String pattern = MessageFormat.format(RedisKey.Enums.WFB_NEED_SEPARATE_ACCOUNTS.getKey(), "*");
        var keys = stringRedisTemplate.keys(pattern);
        if (keys.isEmpty()) {
            return resultList;
        }
        CompletableFuture<Void> execute = YsThread.execute(keys, key -> {
            String value = redisTemplate.opsForValue().get(key);
            if (ObjectUtils.isEmpty(value)) {
                return;
            }
            SeparateAccountListVO vo = new SeparateAccountListVO();
            vo.setWfbSubNo(value);
            resultList.add(vo);
        });
        execute.join();
        return resultList.stream().sorted(Comparator.comparing(SeparateAccountListVO::getWfbSubNo)).collect(Collectors.toList());
    }

    /**
     * 获取总体统计数据
     */
    public ZfbSeparateAccountOverallStatVO getOverallStat(ZfbSeparateAccountStatCon queryDTO) {
        // 构建查询条件
        LambdaQueryWrapper<ZfbSeparateAccountOrder> queryWrapper = buildStatQueryWrapper(queryDTO);

        // 异步查询各种统计数据
        CompletableFuture<List<ZfbSeparateAccountOrder>> allOrdersFuture = YsThread.execute(() -> {
            return zfbSeparateAccountOrderService.list(queryWrapper);
        });

        List<ZfbSeparateAccountOrder> orders = allOrdersFuture.join();

        if (orders.isEmpty()) {
            ZfbSeparateAccountOverallStatVO vo = new ZfbSeparateAccountOverallStatVO()
                    .setTotalSeparateAmount(BigDecimal.ZERO)
                    .setTotalWfbAmount(BigDecimal.ZERO)
                    .setTotalCount(0L)
                    .setAvgSeparateAmount(BigDecimal.ZERO)
                    .setAvgWfbAmount(BigDecimal.ZERO)
                    .setMaxSeparateAmount(BigDecimal.ZERO)
                    .setMinSeparateAmount(BigDecimal.ZERO)
                    .setShopCount(0L)
                    .setZfbAccountCount(0L)
                    .setStatGenerateTime(LocalDateTime.now());
            if (ObjectUtils.isNotEmpty(queryDTO.getStatTimeStart())) {
                vo.setStatTimeStart(DateUtil.stringToLocalDateTime(queryDTO.getStatTimeStart()));
            }
            if (ObjectUtils.isNotEmpty(queryDTO.getStatTimeEnd())) {
                vo.setStatTimeEnd(DateUtil.stringToLocalDateTime(queryDTO.getStatTimeEnd()));
            }
            return vo;
        }

        // 计算统计数据
        BigDecimal totalSeparateAmount = orders.stream()
                .map(order -> new BigDecimal(order.getSeparateAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP))
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal totalWfbAmount = orders.stream()
                .map(order -> new BigDecimal(order.getAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP))
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        Long totalCount = (long) orders.size();

        BigDecimal avgSeparateAmount = totalCount > 0 ?
                totalSeparateAmount.divide(new BigDecimal(totalCount), 2, RoundingMode.HALF_UP) : BigDecimal.ZERO;

        BigDecimal avgWfbAmount = totalCount > 0 ?
                totalWfbAmount.divide(new BigDecimal(totalCount), 2, RoundingMode.HALF_UP) : BigDecimal.ZERO;

        BigDecimal maxSeparateAmount = orders.stream()
                .map(order -> new BigDecimal(order.getSeparateAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP))
                .max(BigDecimal::compareTo)
                .orElse(BigDecimal.ZERO);

        BigDecimal minSeparateAmount = orders.stream()
                .map(order -> new BigDecimal(order.getSeparateAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP))
                .min(BigDecimal::compareTo)
                .orElse(BigDecimal.ZERO);

        Long shopCount = orders.stream()
                .map(ZfbSeparateAccountOrder::getShopCode)
                .distinct()
                .count();

        Long zfbAccountCount = orders.stream()
                .map(ZfbSeparateAccountOrder::getZfbAccount)
                .distinct()
                .count();

        ZfbSeparateAccountOverallStatVO vo = new ZfbSeparateAccountOverallStatVO()
                .setTotalSeparateAmount(totalSeparateAmount)
                .setTotalWfbAmount(totalWfbAmount)
                .setTotalCount(totalCount)
                .setAvgSeparateAmount(avgSeparateAmount)
                .setAvgWfbAmount(avgWfbAmount)
                .setMaxSeparateAmount(maxSeparateAmount)
                .setMinSeparateAmount(minSeparateAmount)
                .setShopCount(shopCount)
                .setZfbAccountCount(zfbAccountCount)
                .setStatGenerateTime(LocalDateTime.now());
        if (ObjectUtils.isNotEmpty(queryDTO.getStatTimeEnd())) {
            vo.setStatTimeEnd(DateUtil.stringToLocalDateTime(queryDTO.getStatTimeEnd()));
        }
        if (ObjectUtils.isNotEmpty(queryDTO.getStatTimeStart())) {
            vo.setStatTimeStart(DateUtil.stringToLocalDateTime(queryDTO.getStatTimeStart()));
        }
        return vo;
    }

    /**
     * 获取时间维度统计数据
     */
    public PageDTO<ZfbSeparateAccountTimeStatVO> getTimeStat(ZfbSeparateAccountStatCon queryDTO) {
        log.info("开始获取支付宝分账时间维度统计数据, 参数: {}", queryDTO);

        try {
            // 构建查询条件
            LambdaQueryWrapper<ZfbSeparateAccountOrder> queryWrapper = buildStatQueryWrapper(queryDTO);

            // 按时间维度分组查询 - 这里需要使用原生SQL来实现时间分组
            // 由于MyBatis-Plus不能很好地支持复杂的分组查询，我们使用原生SQL
            List<ZfbSeparateAccountTimeStatVO> timeStatList = getTimeStatFromDatabase(queryDTO);

            // 分页处理
            int start = (queryDTO.getCurrent() - 1) * queryDTO.getSize();
            int end = Math.min(start + queryDTO.getSize(), timeStatList.size());
            List<ZfbSeparateAccountTimeStatVO> pageData = timeStatList.subList(start, end);

            long total = timeStatList.size();
            long pages = (total + queryDTO.getSize() - 1) / queryDTO.getSize();

            return new PageDTO<>(pages, total, pageData);

        } catch (Exception e) {
            log.error("获取支付宝分账时间维度统计数据异常", e);
            throw new RuntimeException("获取时间维度统计数据失败");
        }
    }

    /**
     * 获取店铺维度统计数据
     */
    public PageDTO<ZfbSeparateAccountShopStatVO> getShopStat(ZfbSeparateAccountStatCon queryDTO) {
        log.info("开始获取支付宝分账店铺维度统计数据, 参数: {}", queryDTO);

        try {
            // 构建查询条件
            LambdaQueryWrapper<ZfbSeparateAccountOrder> queryWrapper = buildStatQueryWrapper(queryDTO);

            // 查询所有数据
            List<ZfbSeparateAccountOrder> orders = zfbSeparateAccountOrderService.list(queryWrapper);

            if (orders.isEmpty()) {
                return new PageDTO<>(0L, 0L, new ArrayList<>());
            }

            // 计算总金额和总笔数用于比例计算
            BigDecimal totalSeparateAmount = orders.stream()
                    .map(order -> new BigDecimal(order.getSeparateAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            long totalCount = orders.size();

            // 按店铺分组统计
            Map<String, List<ZfbSeparateAccountOrder>> shopGroupMap = orders.stream()
                    .collect(Collectors.groupingBy(ZfbSeparateAccountOrder::getShopCode));

            List<ZfbSeparateAccountShopStatVO> shopStatList = shopGroupMap.entrySet().stream()
                    .map(entry -> {
                        String shopCode = entry.getKey();
                        List<ZfbSeparateAccountOrder> shopOrders = entry.getValue();

                        BigDecimal shopSeparateAmount = shopOrders.stream()
                                .map(order -> new BigDecimal(order.getSeparateAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP))
                                .reduce(BigDecimal.ZERO, BigDecimal::add);

                        BigDecimal shopWfbAmount = shopOrders.stream()
                                .map(order -> new BigDecimal(order.getAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP))
                                .reduce(BigDecimal.ZERO, BigDecimal::add);

                        long shopOrderCount = shopOrders.size();

                        BigDecimal avgSeparateAmount = shopOrderCount > 0 ?
                                shopSeparateAmount.divide(new BigDecimal(shopOrderCount), 2, RoundingMode.HALF_UP) : BigDecimal.ZERO;

                        // 计算平均分账比例
                        BigDecimal avgSeparateRatio = shopOrders.stream()
                                .filter(order -> !ObjectUtils.isEmpty(order.getSeparateRatio()))
                                .map(order -> new BigDecimal(order.getSeparateRatio()))
                                .reduce(BigDecimal.ZERO, BigDecimal::add)
                                .divide(new BigDecimal(shopOrders.size()), 2, RoundingMode.HALF_UP);

                        long zfbAccountCount = shopOrders.stream()
                                .map(ZfbSeparateAccountOrder::getZfbAccount)
                                .distinct()
                                .count();

                        // 计算占比
                        BigDecimal amountRatio = totalSeparateAmount.compareTo(BigDecimal.ZERO) > 0 ?
                                shopSeparateAmount.divide(totalSeparateAmount, 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)) : BigDecimal.ZERO;

                        BigDecimal countRatio = totalCount > 0 ?
                                new BigDecimal(shopOrderCount).divide(new BigDecimal(totalCount), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)) : BigDecimal.ZERO;

                        return new ZfbSeparateAccountShopStatVO()
                                .setShopCode(shopCode)
                                .setShopName(shopOrders.get(0).getShopName())
                                .setSeparateAmount(shopSeparateAmount)
                                .setWfbAmount(shopWfbAmount)
                                .setOrderCount(shopOrderCount)
                                .setAvgSeparateAmount(avgSeparateAmount)
                                .setAvgSeparateRatio(avgSeparateRatio)
                                .setZfbAccountCount(zfbAccountCount)
                                .setAmountRatio(amountRatio)
                                .setCountRatio(countRatio);
                    })
                    .sorted((a, b) -> b.getSeparateAmount().compareTo(a.getSeparateAmount()))
                    .collect(Collectors.toList());

            // 分页处理
            int start = (queryDTO.getCurrent() - 1) * queryDTO.getSize();
            int end = Math.min(start + queryDTO.getSize(), shopStatList.size());
            List<ZfbSeparateAccountShopStatVO> pageData = shopStatList.subList(start, end);

            long total = shopStatList.size();
            long pages = (total + queryDTO.getSize() - 1) / queryDTO.getSize();

            return new PageDTO<>(pages, total, pageData);

        } catch (Exception e) {
            log.error("获取支付宝分账店铺维度统计数据异常", e);
            throw new RuntimeException("获取店铺维度统计数据失败");
        }
    }

    /**
     * 获取支付宝账户维度统计数据
     */
    public PageDTO<ZfbSeparateAccountAccountStatVO> getAccountStat(ZfbSeparateAccountStatCon queryDTO) {
        log.info("开始获取支付宝分账账户维度统计数据, 参数: {}", queryDTO);

        try {
            // 构建查询条件
            LambdaQueryWrapper<ZfbSeparateAccountOrder> queryWrapper = buildStatQueryWrapper(queryDTO);

            // 查询所有数据
            List<ZfbSeparateAccountOrder> orders = zfbSeparateAccountOrderService.list(queryWrapper);

            if (orders.isEmpty()) {
                return new PageDTO<>(0L, 0L, new ArrayList<>());
            }

            // 计算总金额和总笔数用于比例计算
            BigDecimal totalSeparateAmount = orders.stream()
                    .map(order -> new BigDecimal(order.getSeparateAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            long totalCount = orders.size();

            // 按支付宝账户分组统计
            Map<String, List<ZfbSeparateAccountOrder>> accountGroupMap = orders.stream()
                    .collect(Collectors.groupingBy(ZfbSeparateAccountOrder::getZfbAccount));

            List<ZfbSeparateAccountAccountStatVO> accountStatList = accountGroupMap.entrySet().stream()
                    .map(entry -> {
                        String zfbAccount = entry.getKey();
                        List<ZfbSeparateAccountOrder> accountOrders = entry.getValue();

                        BigDecimal accountSeparateAmount = accountOrders.stream()
                                .map(order -> new BigDecimal(order.getSeparateAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP))
                                .reduce(BigDecimal.ZERO, BigDecimal::add);

                        BigDecimal accountWfbAmount = accountOrders.stream()
                                .map(order -> new BigDecimal(order.getAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP))
                                .reduce(BigDecimal.ZERO, BigDecimal::add);

                        long accountOrderCount = accountOrders.size();

                        BigDecimal avgSeparateAmount = accountOrderCount > 0 ?
                                accountSeparateAmount.divide(new BigDecimal(accountOrderCount), 2, RoundingMode.HALF_UP) : BigDecimal.ZERO;

                        long shopCount = accountOrders.stream()
                                .map(ZfbSeparateAccountOrder::getShopCode)
                                .distinct()
                                .count();

                        String shopNames = accountOrders.stream()
                                .map(ZfbSeparateAccountOrder::getShopName)
                                .distinct()
                                .collect(Collectors.joining(", "));

                        // 计算占比
                        BigDecimal amountRatio = totalSeparateAmount.compareTo(BigDecimal.ZERO) > 0 ?
                                accountSeparateAmount.divide(totalSeparateAmount, 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)) : BigDecimal.ZERO;

                        BigDecimal countRatio = totalCount > 0 ?
                                new BigDecimal(accountOrderCount).divide(new BigDecimal(totalCount), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)) : BigDecimal.ZERO;

                        return new ZfbSeparateAccountAccountStatVO()
                                .setZfbAccount(zfbAccount)
                                .setZfbName(accountOrders.get(0).getZfbName())
                                .setSeparateAmount(accountSeparateAmount)
                                .setWfbAmount(accountWfbAmount)
                                .setOrderCount(accountOrderCount)
                                .setAvgSeparateAmount(avgSeparateAmount)
                                .setShopCount(shopCount)
                                .setShopNames(shopNames)
                                .setAmountRatio(amountRatio)
                                .setCountRatio(countRatio);
                    })
                    .sorted((a, b) -> b.getSeparateAmount().compareTo(a.getSeparateAmount()))
                    .collect(Collectors.toList());

            // 分页处理
            int start = (queryDTO.getCurrent() - 1) * queryDTO.getSize();
            int end = Math.min(start + queryDTO.getSize(), accountStatList.size());
            List<ZfbSeparateAccountAccountStatVO> pageData = accountStatList.subList(start, end);

            long total = accountStatList.size();
            long pages = (total + queryDTO.getSize() - 1) / queryDTO.getSize();

            return new PageDTO<>(pages, total, pageData);

        } catch (Exception e) {
            log.error("获取支付宝分账账户维度统计数据异常", e);
            throw new RuntimeException("获取账户维度统计数据失败");
        }
    }

    /**
     * 获取分账比例维度统计数据
     */
    public PageDTO<ZfbSeparateAccountRatioStatVO> getRatioStat(ZfbSeparateAccountStatCon queryDTO) {
        log.info("开始获取支付宝分账比例维度统计数据, 参数: {}", queryDTO);

        try {
            // 构建查询条件
            LambdaQueryWrapper<ZfbSeparateAccountOrder> queryWrapper = buildStatQueryWrapper(queryDTO);

            // 查询所有数据
            List<ZfbSeparateAccountOrder> orders = zfbSeparateAccountOrderService.list(queryWrapper);

            if (orders.isEmpty()) {
                return new PageDTO<>(0L, 0L, new ArrayList<>());
            }

            // 计算总金额和总笔数用于比例计算
            BigDecimal totalSeparateAmount = orders.stream()
                    .map(order -> new BigDecimal(order.getSeparateAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            long totalCount = orders.size();

            // 按分账比例分组统计
            Map<String, List<ZfbSeparateAccountOrder>> ratioGroupMap = orders.stream()
                    .filter(order -> !ObjectUtils.isEmpty(order.getSeparateRatio()))
                    .collect(Collectors.groupingBy(ZfbSeparateAccountOrder::getSeparateRatio));

            List<ZfbSeparateAccountRatioStatVO> ratioStatList = ratioGroupMap.entrySet().stream()
                    .map(entry -> {
                        String separateRatio = entry.getKey();
                        List<ZfbSeparateAccountOrder> ratioOrders = entry.getValue();

                        BigDecimal ratioSeparateAmount = ratioOrders.stream()
                                .map(order -> new BigDecimal(order.getSeparateAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP))
                                .reduce(BigDecimal.ZERO, BigDecimal::add);

                        BigDecimal ratioWfbAmount = ratioOrders.stream()
                                .map(order -> new BigDecimal(order.getAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP))
                                .reduce(BigDecimal.ZERO, BigDecimal::add);

                        long ratioOrderCount = ratioOrders.size();

                        BigDecimal avgSeparateAmount = ratioOrderCount > 0 ?
                                ratioSeparateAmount.divide(new BigDecimal(ratioOrderCount), 2, RoundingMode.HALF_UP) : BigDecimal.ZERO;

                        long shopCount = ratioOrders.stream()
                                .map(ZfbSeparateAccountOrder::getShopCode)
                                .distinct()
                                .count();

                        long zfbAccountCount = ratioOrders.stream()
                                .map(ZfbSeparateAccountOrder::getZfbAccount)
                                .distinct()
                                .count();

                        // 计算占比
                        BigDecimal amountRatio = totalSeparateAmount.compareTo(BigDecimal.ZERO) > 0 ?
                                ratioSeparateAmount.divide(totalSeparateAmount, 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)) : BigDecimal.ZERO;

                        BigDecimal countRatio = totalCount > 0 ?
                                new BigDecimal(ratioOrderCount).divide(new BigDecimal(totalCount), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)) : BigDecimal.ZERO;

                        return new ZfbSeparateAccountRatioStatVO()
                                .setSeparateRatio(separateRatio)
                                .setSeparateAmount(ratioSeparateAmount)
                                .setWfbAmount(ratioWfbAmount)
                                .setOrderCount(ratioOrderCount)
                                .setAvgSeparateAmount(avgSeparateAmount)
                                .setShopCount(shopCount)
                                .setZfbAccountCount(zfbAccountCount)
                                .setAmountRatio(amountRatio)
                                .setCountRatio(countRatio);
                    })
                    .sorted((a, b) -> b.getSeparateAmount().compareTo(a.getSeparateAmount()))
                    .collect(Collectors.toList());

            // 分页处理
            int start = (queryDTO.getCurrent() - 1) * queryDTO.getSize();
            int end = Math.min(start + queryDTO.getSize(), ratioStatList.size());
            List<ZfbSeparateAccountRatioStatVO> pageData = ratioStatList.subList(start, end);

            long total = ratioStatList.size();
            long pages = (total + queryDTO.getSize() - 1) / queryDTO.getSize();

            return new PageDTO<>(pages, total, pageData);

        } catch (Exception e) {
            log.error("获取支付宝分账比例维度统计数据异常", e);
            throw new RuntimeException("获取比例维度统计数据失败");
        }
    }

    /**
     * 构建统计查询条件
     */
    private LambdaQueryWrapper<ZfbSeparateAccountOrder> buildStatQueryWrapper(ZfbSeparateAccountStatCon queryDTO) {
        LambdaQueryWrapper<ZfbSeparateAccountOrder> queryWrapper = new LambdaQueryWrapper<>();

        // 店铺编号
        if (!ObjectUtils.isEmpty(queryDTO.getShopCode())) {
            queryWrapper.like(ZfbSeparateAccountOrder::getShopCode, queryDTO.getShopCode().trim());
        }

        // 店铺名称
        if (!ObjectUtils.isEmpty(queryDTO.getShopName())) {
            queryWrapper.like(ZfbSeparateAccountOrder::getShopName, queryDTO.getShopName().trim());
        }

        // 支付宝账户
        if (!ObjectUtils.isEmpty(queryDTO.getZfbAccount())) {
            queryWrapper.like(ZfbSeparateAccountOrder::getZfbAccount, queryDTO.getZfbAccount().trim());
        }

        // 支付宝姓名
        if (!ObjectUtils.isEmpty(queryDTO.getZfbName())) {
            queryWrapper.like(ZfbSeparateAccountOrder::getZfbName, queryDTO.getZfbName().trim());
        }

        // 统计时间范围
        if (!ObjectUtils.isEmpty(queryDTO.getStatTimeStart())) {
            queryWrapper.ge(ZfbSeparateAccountOrder::getTransTime, queryDTO.getStatTimeStart());
        }
        if (!ObjectUtils.isEmpty(queryDTO.getStatTimeEnd())) {
            queryWrapper.le(ZfbSeparateAccountOrder::getTransTime, queryDTO.getStatTimeEnd());
        }

        // 默认按交易时间排序
        queryWrapper.orderByDesc(ZfbSeparateAccountOrder::getTransTime);

        return queryWrapper;
    }

    /**
     * 从数据库获取时间维度统计数据
     * 由于时间分组需要使用SQL函数，这里简化处理，实际可以使用MyBatis XML配置
     */
    private List<ZfbSeparateAccountTimeStatVO> getTimeStatFromDatabase(ZfbSeparateAccountStatCon queryDTO) {
        // 这里先用Java代码模拟，实际应该使用SQL GROUP BY DATE_FORMAT等函数
        LambdaQueryWrapper<ZfbSeparateAccountOrder> queryWrapper = buildStatQueryWrapper(queryDTO);
        List<ZfbSeparateAccountOrder> orders = zfbSeparateAccountOrderService.list(queryWrapper);

        String timeDimension = !ObjectUtils.isEmpty(queryDTO.getTimeDimension()) ? queryDTO.getTimeDimension() : "day";

        // 按时间维度分组
        Map<String, List<ZfbSeparateAccountOrder>> timeGroupMap = orders.stream()
                .collect(Collectors.groupingBy(order -> {
                    LocalDateTime transTime = order.getTransTime();
                    if (transTime == null) return "未知";

                    switch (timeDimension) {
                        case "month":
                            return transTime.getYear() + "-" + String.format("%02d", transTime.getMonthValue());
                        case "year":
                            return String.valueOf(transTime.getYear());
                        default: // day
                            return transTime.getYear() + "-" + String.format("%02d", transTime.getMonthValue()) + "-" + String.format("%02d", transTime.getDayOfMonth());
                    }
                }));

        return timeGroupMap.entrySet().stream()
                .map(entry -> {
                    String timeLabel = entry.getKey();
                    List<ZfbSeparateAccountOrder> timeOrders = entry.getValue();

                    BigDecimal separateAmount = timeOrders.stream()
                            .map(order -> new BigDecimal(order.getSeparateAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP))
                            .reduce(BigDecimal.ZERO, BigDecimal::add);

                    BigDecimal wfbAmount = timeOrders.stream()
                            .map(order -> new BigDecimal(order.getAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP))
                            .reduce(BigDecimal.ZERO, BigDecimal::add);

                    long orderCount = timeOrders.size();

                    BigDecimal avgSeparateAmount = orderCount > 0 ?
                            separateAmount.divide(new BigDecimal(orderCount), 2, RoundingMode.HALF_UP) : BigDecimal.ZERO;

                    long shopCount = timeOrders.stream()
                            .map(ZfbSeparateAccountOrder::getShopCode)
                            .distinct()
                            .count();

                    long zfbAccountCount = timeOrders.stream()
                            .map(ZfbSeparateAccountOrder::getZfbAccount)
                            .distinct()
                            .count();

                    return new ZfbSeparateAccountTimeStatVO()
                            .setTimeLabel(timeLabel)
                            .setSeparateAmount(separateAmount)
                            .setWfbAmount(wfbAmount)
                            .setOrderCount(orderCount)
                            .setAvgSeparateAmount(avgSeparateAmount)
                            .setShopCount(shopCount)
                            .setZfbAccountCount(zfbAccountCount);
                })
                .sorted((a, b) -> a.getTimeLabel().compareTo(b.getTimeLabel()))
                .collect(Collectors.toList());
    }

    /**
     * 获取综合统计数据（包含所有维度的TOP数据）
     */
    public ZfbSeparateAccountComprehensiveStatVO getComprehensiveStat(ZfbSeparateAccountStatCon queryDTO) {
        log.info("开始获取支付宝分账综合统计数据, 参数: {}", queryDTO);
        
        try {
            // 异步并发获取各维度统计数据，提升性能
            CompletableFuture<ZfbSeparateAccountOverallStatVO> overallStatFuture = YsThread.execute(() -> {
                return getOverallStat(queryDTO);
            });
            
            // 设置TOP 10限制的查询条件
            ZfbSeparateAccountStatCon top10QueryDTO = new ZfbSeparateAccountStatCon();
            BeanUtils.copyProperties(queryDTO, top10QueryDTO);
            top10QueryDTO.setCurrent(1);
            top10QueryDTO.setSize(10);
            
            CompletableFuture<List<ZfbSeparateAccountTimeStatVO>> timeStatFuture = YsThread.execute(() -> {
                return getTimeStat(top10QueryDTO).getRecords();
            });
            
            CompletableFuture<List<ZfbSeparateAccountShopStatVO>> shopStatFuture = YsThread.execute(() -> {
                return getShopStat(top10QueryDTO).getRecords();
            });
            
            CompletableFuture<List<ZfbSeparateAccountAccountStatVO>> accountStatFuture = YsThread.execute(() -> {
                return getAccountStat(top10QueryDTO).getRecords();
            });
            
            CompletableFuture<List<ZfbSeparateAccountRatioStatVO>> ratioStatFuture = YsThread.execute(() -> {
                return getRatioStat(top10QueryDTO).getRecords();
            });
            
            // 等待所有异步任务完成
            ZfbSeparateAccountOverallStatVO overallStat = overallStatFuture.join();
            List<ZfbSeparateAccountTimeStatVO> timeStatList = timeStatFuture.join();
            List<ZfbSeparateAccountShopStatVO> shopStatList = shopStatFuture.join();
            List<ZfbSeparateAccountAccountStatVO> accountStatList = accountStatFuture.join();
            List<ZfbSeparateAccountRatioStatVO> ratioStatList = ratioStatFuture.join();
            
            return new ZfbSeparateAccountComprehensiveStatVO()
                    .setOverallStat(overallStat)
                    .setTimeStatList(timeStatList)
                    .setShopStatList(shopStatList)
                    .setAccountStatList(accountStatList)
                    .setRatioStatList(ratioStatList);
                    
        } catch (Exception e) {
            log.error("获取支付宝分账综合统计数据异常", e);
            throw new RuntimeException("获取综合统计数据失败");
        }
    }

}